/*
 * Copyright 2010-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jslet.paas.modelmeta.model;

import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "TMetaData")
public class ModelMeta implements Serializable
{
	private static final long serialVersionUID = 5895394197535800681L;

	@Id
	private int modelId;

	private String name;

	private String description;

	private String packageName;

	private String dbObject;
	
	private int dbObjectType = DBObjectType.TABLE;

	private String keyField;

	private String inputValueField;

	private String displayValueField;

	private String parentField;

	private String levelField;

	private String tenant;

	@OneToMany(mappedBy = "modelMeta", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	private List<FieldMeta> fields;

	@OneToMany(mappedBy = "modelMeta", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	private List<FieldMeta> filters;
	
	public int getModelId()
	{
		return modelId;
	}

	public void setModelId(int modelId)
	{
		this.modelId = modelId;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public String getDescription()
	{
		return description;
	}

	public void setDescription(String desc)
	{
		this.description = desc;
	}

	public String getPackageName()
	{
		return packageName;
	}

	public void setPackageName(String packageName)
	{
		this.packageName = packageName;
	}

	public int getDbObjectType()
	{
		return dbObjectType;
	}

	public void setDbObjectType(int dbObjectType)
	{
		this.dbObjectType = dbObjectType;
	}

	public String getDbObject()
	{
		return dbObject;
	}

	public void setDbObject(String dbObject)
	{
		this.dbObject = dbObject;
	}

	public String getKeyField()
	{
		return keyField;
	}

	public void setKeyField(String keyField)
	{
		this.keyField = keyField;
	}

	public String getInputValueField()
	{
		return inputValueField;
	}

	public void setInputValueField(String inputValueField)
	{
		this.inputValueField = inputValueField;
	}

	public String getDisplayValueField()
	{
		return displayValueField;
	}

	public void setDisplayValueField(String displayValueField)
	{
		this.displayValueField = displayValueField;
	}

	public String getParentField()
	{
		return parentField;
	}

	public void setParentField(String parentField)
	{
		this.parentField = parentField;
	}

	public String getLevelField()
	{
		return levelField;
	}

	public void setLevelField(String levelField)
	{
		this.levelField = levelField;
	}

	public String getTenant()
	{
		return tenant;
	}

	public void setTenant(String tenant)
	{
		this.tenant = tenant;
	}

	public List<FieldMeta> getFields()
	{
		return fields;
	}

	public void setFields(List<FieldMeta> fields)
	{
		this.fields = fields;
	}

	public List<FieldMeta> getFilters()
	{
		return filters;
	}

	public void setFilters(List<FieldMeta> filters)
	{
		this.filters = filters;
	}

	@Override
	public boolean equals(Object obj)
	{
		if (obj instanceof ModelMeta)
		{
			return this.getModelId() == ((ModelMeta) obj).getModelId();
		}
		return false;
	}

	public void copyFrom(ModelMeta bizModel)
	{
		if (bizModel == null)
		{
			return;
		}
		this.setName(bizModel.getName());
		this.setDescription(bizModel.getDescription());
		this.setPackageName(bizModel.getPackageName());
		this.setDbObject(bizModel.getDbObject());
		this.setDbObjectType(bizModel.getDbObjectType());
		this.setKeyField(bizModel.getKeyField());
		this.setDisplayValueField(bizModel.getDisplayValueField());
		this.setInputValueField(bizModel.getInputValueField());
		this.setParentField(bizModel.getParentField());
		this.setLevelField(bizModel.getLevelField());
		this.setTenant(bizModel.getTenant());

		this.mergeFields(this.getFields(), bizModel.getFields());
		this.mergeFields(this.getFilters(), bizModel.getFilters());
	}
	
	private void mergeFields(List<FieldMeta> fields, List<FieldMeta> srcFields){
		int count;
		FieldMeta thisBf;
		int[] indexArr = new int[fields.size()];

		for (FieldMeta bf : srcFields)
		{
			count = fields.indexOf(bf);
			if (count < 0)
			{
				thisBf = new FieldMeta();
				thisBf.setModelMeta(this);
			}
			else
			{
				thisBf = fields.get(count);
				indexArr[count] = 1;
			}
			thisBf.copyFrom(bf);
		}
		// Remove all items that not in new list
		for (int i = indexArr.length - 1; i >= 0; i--)
		{
			if (indexArr[i] == 0)
			{
				fields.remove(i);
			}
		}
		
	}
}
